package com.zeyu.framework.core.web.utils.function;

import com.zeyu.framework.utils.Exceptions;

import org.beetl.core.Context;
import org.beetl.core.Function;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

/**
 * 400错误处理
 * Created by zeyuphoenix on 2016/3/30.
 */
public class ReqErrorTrace implements Function {

    // ================================================================
    // Constants
    // ================================================================

    // ================================================================
    // Fields
    // ================================================================

    // ================================================================
    // Constructors
    // ================================================================

    // ================================================================
    // Methods from/for super Interfaces or SuperClass
    // ================================================================

    @Override
    public Object call(Object[] paras, Context ctx) {
        // 参数为空
        if (paras == null || paras.length == 0) {
            return "";
        }
        HttpServletRequest request = (HttpServletRequest) ctx.getGlobal("request");
        HttpServletResponse response = (HttpServletResponse) ctx.getGlobal("response");

        response.setStatus(400);

        // 获取异常类
        Throwable ex = Exceptions.getThrowable(request);

        // 编译错误信息
        StringBuilder sb = new StringBuilder("错误信息：\n");
        if (ex != null) {
            if (ex instanceof BindException) {
                for (ObjectError e : ((BindException) ex).getGlobalErrors()) {
                    sb.append("☆" + e.getDefaultMessage() + "(" + e.getObjectName() + ")\n");
                }
                for (FieldError e : ((BindException) ex).getFieldErrors()) {
                    sb.append("☆" + e.getDefaultMessage() + "(" + e.getField() + ")\n");
                }
                LoggerFactory.getLogger("400.jsp").warn(ex.getMessage(), ex);
            } else if (ex instanceof ConstraintViolationException) {
                for (ConstraintViolation<?> v : ((ConstraintViolationException) ex).getConstraintViolations()) {
                    sb.append("☆" + v.getMessage() + "(" + v.getPropertyPath() + ")\n");
                }
            } else {
                //sb.append(Exceptions.getStackTraceAsString(ex));
                sb.append("☆" + ex.getMessage());
            }
        } else {
            sb.append("未知错误.\n\n");
        }

        // 如果是异步请求或是手机端，则直接返回信息
        if (paras[0] != null && Boolean.valueOf(paras[0].toString())) {
            try {
                response.getOutputStream().print(sb.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return sb.toString();
    }

    // ================================================================
    // Public or Protected Methods
    // ================================================================

    // ================================================================
    // Getter & Setter
    // ================================================================

    // ================================================================
    // Private Methods
    // ================================================================

    // ================================================================
    // Inner or Anonymous Class
    // ================================================================

    // ================================================================
    // Test Methods
    // ================================================================
}
